#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QSettings"
#include <QDebug>
#include <QTimer>
#include <QFile>
#include <QPropertyAnimation>

#include <QSysInfo>
#include <QNetworkAccessManager>
#include <QPixmap>
#include <QNetworkReply>

#include "formshell.h"
#include "formtestdelete.h"
#include "creflection.h"

#include <QScreen>

// json
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

//
#include "popmainwnd.h"
#include "gpuinfo/gpuinfo.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
//    ui->bannerImg_Tgroup->setRoundedRectRadiux(4, 4);
    m_engineView = new QWebEngineView();
//    m_engineView->setUrl(QUrl("https://www.baidu.com"));
//    m_engineView->load(QUrl("file:////index.html"));
//    m_engineView->show();
//    printDeviceInfo();
    m_timerID = startTimer(100);
    this->show();

    ui->title->setText(QString("<html><body><a style=\"text-overflow: ellipsis;\">نساتهتسهنيننيننين.7777777777777777777777777777777777777777777777777777777777777777777777txt</a></body></html>"));
//    ui->title->setText(QString("نساتهتسهنيننيننين.txt"));

    QTimer::singleShot(2*1000, this, [this]{
        ui->colorTest->setStyleSheet("background-color: rgb(255, 255, 255);");
    });

    QString urlOri = "++.jpg";
    qDebug() << __FUNCTION__ << "-----> encode result: " << QUrl::toPercentEncoding(urlOri);    // "%2B%2B.jpg"

    quint64 reviewTime = 7299;
    QString timestr("%1:%2:%3");
    timestr = timestr.arg(reviewTime/3600).arg(reviewTime%3600/60, 2, 10, QChar('0')).arg(reviewTime%3600%60, 2, 10, QChar('0'));   // "2:01:39"
    qDebug() << __FUNCTION__ << "-----------> time: " << timestr;

    ui->label->setTextFormat(Qt::RichText);
    QString str1 = "<font color='#FFFFFF' style=\"border-radius:0px 4px 6px 4px; background: #000000; padding: 4px 10px; margin-right: 20px\">Japan</font><font color='#2F3741'>hello</font>";
    QString str2 = "<p style=\"font-family:verdana;color:red\">This text is in Verdana and red</p>";
    QString str3 = "<p style=\"font-size:30px\">This text is 30 pixels high</p>";
    QString str4 = "<body style=\"background-color:PowderBlue;\">";
    QString str5 = "<p style=\"font-size:30px; background: #000000; padding-left: 4px; padding-right: 10px; margin-right: 20px\"><font color='#FFFFFF'>Japan</font></p>";
    QString str6 = "<font color='#FFFFFF' style=\"font-size: 25px; border-style: solid; border-color: #DC143C; background: #000000;\">Japan Us</font><font color='#2F3741'>hello</font>";
    ui->label->setText(str6);
    qDebug() << __FUNCTION__ << "---->str6: " << str6 << "str.size: " << str6.size();
    QString lp1 = "Hello World!";
    QString lp2 = "World!";
    QString lp3 = "Hello ";
    qDebug() << __FUNCTION__ << "----------> lp: " << lp1.right(3);

    qDebug() << __FUNCTION__ << "------------> system INfo: " << QSysInfo::productType() << "  version: " << QSysInfo::productVersion();

    ui->label_4->setStyleSheet("");
    ui->label_4->setAutoFillBackground(true);
    QPalette p = ui->label_4->palette();
    p.setColor(QPalette::Window, QColor(0, 125, 154));
    ui->label_4->setPalette(p);

    QLabel* label_5 = new QLabel(ui->widget_3);
    label_5->setFixedSize(100, 100);
    label_5->setPalette(*(new QPalette(Qt::green)));
    label_5->setAutoFillBackground(true);
    label_5->show();
//    QPalette p1 = label_5->palette();
//    p1.setColor(QPalette::Window, QColor(0, 125, 154));
//    label_5->setPalette(p1);
//    label_5->setStyleSheet(QString::fromUtf8("background-color: rgb(255, 255, 0);"));

//    ui->bannerImg_Tgroup->setPixmap(QPixmap(":/resDir/111.png"));
    getPicByUrl("");

    // load big-monkey picture.
    loadPicByLocal();

    // get the local device info, like screen info.
    getLocalDeviceInfo();

    // get Json info.
    QString testJson_1 = "{\"appIds\":[48,49,50,51,52,53,54,55,56,57,58,59],\"type\":2}";
    QString testJson_2 = "{\"type\":3}";
    getJsonInfo(testJson_1.toUtf8());
    getJsonInfo(testJson_2.toUtf8());

    // install a event filter
    ui->btnTestHover->installEventFilter(this);
}

MainWindow::~MainWindow()
{
    delete m_engineView;
    delete ui;
}


void MainWindow::printDeviceInfo()
{
    qDebug() << "----------> " << Q_FUNC_INFO;
    QSettings *DeviceName = new QSettings("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\Tablet PC", QSettings::NativeFormat);
//    QString isTablet = DeviceName->value("isTabletPC").toString();
    QString deviceKind = DeviceName->value("DeviceKind").toString();
//    qDebug() << "================> isTablet: " << isTablet << "  deviceKind: " << deviceKind;
//    ui->isTablet->setText(isTablet);
    ui->kind->setText(deviceKind);
//    QString ret = "========> isTablet: %1  deviceKind: %2";
//    ui->label->setText(ret.arg(isTablet).arg(deviceKind));

}

void MainWindow::timerEvent(QTimerEvent *event)
{
//    QTime time = QTime::fromString("1mm12car00", "m'mm'hcarss");
    QTime time01 = QTime::currentTime();
//    qDebug() << "========> timer event call, currentTime: [" << time01 << "]";
    if (m_timerID == event->timerId()) {
//        showPos();
    }
}

bool MainWindow::eventFilter(QObject *obj, QEvent *ev)
{
    if (obj == ui->btnTestHover) {
        if (ev->type() == QEvent::Enter) {
            if (m_pPopMainWnd == Q_NULLPTR) {
                m_pPopMainWnd = new PopMainWnd(this);
            }

            QSize szItem = ui->btnTestHover->geometry().size();
            QSize szWnd = m_pPopMainWnd->geometry().size();
            QPoint offset((szItem.width() - szWnd.width()) / 2, szItem.height());
            QPoint pt = ui->btnTestHover->mapToGlobal(offset);
            m_pPopMainWnd->show();
            m_pPopMainWnd->move(pt);
        } else if (ev->type() == QEvent::Leave) {
            m_pPopMainWnd->close();
            m_pPopMainWnd->deleteLater();
            m_pPopMainWnd = Q_NULLPTR;
        }
    }

    return false;
}

void MainWindow::showPos()
{
    // Get mouse pos from global
    QPoint ptCursor = mapFromGlobal(QCursor::pos());
    bool bInRect = rect().contains(ptCursor);

    qDebug() << "---> bInRect: [" << bInRect << "] rect: [" << rect() << "] Cursor::pos(): [" << QCursor::pos() << "] ptCursor: [" << ptCursor <<"]";
}

void MainWindow::on_openFileBtn_clicked()
{
//    QFile file("C://Users//renleilei//Pictures//Saved Pictures//CCTalk6.0.6测试用例(new).xlsx");
//    bool bRet = file.open(QIODevice::ReadOnly);
//    qDebug() << __FUNCTION__ << "---------> be called! read ret: " << bRet;
//    file.close();

    FILE* tempFile = Q_NULLPTR;
    QString filename = "C://Users//renleilei//Pictures//Saved Pictures//CCTalk6.0.6测试用例(new).xlsx";
//    wchar_t wide_file_name[1024] = L("");
    wchar_t wide_file_name1[1024] = {'r','b', 0};
    errno_t err = _wfopen_s(&tempFile, filename.toStdWString().c_str(), wide_file_name1);
    qDebug()<<""<<err;
}

void MainWindow::on_openFileBtn_w_clicked()
{
    QFile file("C://Users//renleilei//Pictures//Saved Pictures//CCTalk6.0.6测试用例(new).xlsx");
    bool bRet = file.open(QIODevice::WriteOnly);
    qDebug() << __FUNCTION__ << "---------> be called! write ret: " << bRet;
    file.close();
}

void MainWindow::on_pushButton_clicked()
{
    quint64 percent = 0;
    quint64 studyTime = 950;
    quint64 totalTime = 96000;
    percent = studyTime * 100 / totalTime;
    qDebug() << __func__ << "--------> be called! " << percent;
}

void MainWindow::onNetworkReply(QNetworkReply *reply)
{
    qDebug() << __func__ << "---------> be called! size: " << reply->readBufferSize();
    QPixmap pix;
    QByteArray data = reply->readAll();
    pix.loadFromData(data, "JPG");
//    pix.save("C://Users//renleilei//Pictures//Saved Pictures//demo02.jpg", "JPG", 100);

    ui->label_monkey->setPixmap(pix);
//    ui->bannerImg_Tgroup->setPixmap(pix);

    // test the qlabel
    QImage imageObj;
    imageObj.load("C://Users//renleilei//Pictures//Saved Pictures//big_monkey.jpg");
    QPixmap pixmap = QPixmap::fromImage(imageObj);
    int width = ui->bannerImg_Tgroup->width();
    int height = ui->bannerImg_Tgroup->height();
//    QPixmap fitPixmap = pixmap.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);  // 饱满填充
//    QPixmap fitPixmap = pixmap.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);  // 按比例缩放
    QPixmap fitPixmap = pixmap.scaled(width, height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);  // 按比例缩放并填充

    QPixmap radiusPixmap = generatePixmap(fitPixmap, 5);

    ui->bannerImg_Tgroup->setPixmap(fitPixmap);
}

void MainWindow::showAnimation()
{
    //
}

void MainWindow::getPicByUrl(QString url)
{
    QNetworkAccessManager *managerPtr;
    managerPtr = new QNetworkAccessManager(this);
    connect(managerPtr, &QNetworkAccessManager::finished, this, &MainWindow::onNetworkReply);
    QNetworkRequest request;
//    request.setUrl(QUrl("https://cc.hjfile.cn/cc/img/20190826/2019082610592393726560.jpg"));
//    managerPtr->get(request);

    // use smart ptr. (will be delete, but picture cannot show.)
//    std::shared_ptr<QNetworkAccessManager> sp = std::make_shared<QNetworkAccessManager>();
//    connect(sp.get(), &QNetworkAccessManager::finished, this, &MainWindow::onNetworkReply);
//    QNetworkRequest request;
//    request.setUrl(QUrl("https://cc.hjfile.cn/cc/img/20190826/2019082610592393726560.jpg"));
//    sp.get()->get(request);

    return;
}

QPixmap MainWindow::generatePixmap(const QPixmap &src, const int &radius)
{
    if (src.isNull()) {
        return src;
    }

    // compress the pixmap
//    QPixmap pixmap = scaledPixmap();
    QPixmap pixmap = src.scaled(2*radius, 2*radius, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

    QPixmap dest(2*radius, 2*radius);
    dest.fill(Qt::transparent);
    QPainter painter(&dest);

    // 抗锯齿 +平滑处理
    painter.setRenderHints(QPainter::Antialiasing, true);
    painter.setRenderHints(QPainter::SmoothPixmapTransform, true);

    // 裁剪为圆角
    QPainterPath path;
    path.addEllipse(0, 0, 2*radius, 2*radius);
    painter.setClipPath(path);
    painter.drawPixmap(0, 0, 2*radius, 2*radius, pixmap);

    qDebug() << __func__ << "-------> call end!";
    return dest;
}

void MainWindow::on_btn_next_clicked()
{
    if (!m_uPtrShell) {
        m_uPtrShell = std::make_unique<FormShell>();
    }

    hide();
    m_uPtrShell->show();
}

void MainWindow::on_btn_Ani_clicked()
{
    QString scrollText = ui->ScrollCopyrightLabel->text();
    if (scrollText.isEmpty()) {
        return;
    }

    if (!m_scrollAnimation) {
        m_scrollAnimation = new QPropertyAnimation(this, "scrollPos");
    }

//    if (m_scrollAnimation->state() == QPropertyAnimation::Running) {
//        return;
//    }

    QFontMetrics fm(ui->ScrollCopyrightLabel->font());
    int textWidth = fm.width(scrollText);

    ui->ScrollCopyrightLabel->resize(textWidth, ui->ScrollCopyrightLabel->height());

    qDebug() << __func__ << "-----------> be called! text: " << scrollText;
//    QPropertyAnimation *animation = new QPropertyAnimation(ui->ScrollCopyrightLabel, "geometry");

    m_scrollAnimation->setDuration(1000);
    m_scrollAnimation->setStartValue(0);
    m_scrollAnimation->setEndValue(-300);
    m_scrollAnimation->setEasingCurve(QEasingCurve::Linear);
    m_scrollAnimation->start();

    QTimer::singleShot(2000, this, [=](){
        if (m_scrollAnimation != Q_NULLPTR) {
            qDebug() << __func__ << "----------> time out, animation stop!";
            m_scrollAnimation->stop();
        }
    });
}

void MainWindow::setScrollPos(qint32 xPos)
{
    qDebug() << __func__;
    if (xPos == m_scrollPos) {
        return;
    }

    if (!m_scrollAnimation) {
        return;
    }

    if (m_scrollAnimation->state() == QPropertyAnimation::Running) {
        static qint64 timeT = 0;

        QDateTime time = QDateTime::currentDateTime();
        qint64 curTimeT = time.toMSecsSinceEpoch();

        if( curTimeT - timeT > 50 ) {
            timeT = curTimeT;
        } else {
            return;
        }
    }

    m_scrollPos = xPos;

    QPoint labelPos = ui->ScrollCopyrightLabel->pos();
    ui->ScrollCopyrightLabel->move(xPos, labelPos.y());

    emit scrollPosChanged();
}

void MainWindow::loadPicByLocal()
{
    qDebug() << __func__ << "---------> be called! ";
    QImage imageObj;
    imageObj.load("C://Users//s4260//Pictures//Saved Pictures//big_monkey.jpg");
    QPixmap pixmap = QPixmap::fromImage(imageObj);
    if (pixmap.isNull()) {
        qDebug() << __func__ << "---------> pixmap is empty!";
        return;
    }

    ui->label_monkey->setPixmap(pixmap);

    int width = ui->bannerImg_Tgroup->width();
    int height = ui->bannerImg_Tgroup->height();
//    QPixmap fitPixmap = pixmap.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);  // 饱满填充
//    QPixmap fitPixmap = pixmap.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);  // 按比例缩放
    QPixmap fitPixmap = pixmap.scaled(width, height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);  // 按比例缩放并填充

    QPixmap radiusPixmap = generatePixmap(fitPixmap, 5);
    ui->bannerImg_Tgroup->setPixmap(fitPixmap);
}

void MainWindow::getLocalDeviceInfo()
{
    QDesktopWidget* deskTopWidget = QApplication::desktop();
    QScreen* pScreen = QGuiApplication::primaryScreen();
    if (deskTopWidget == nullptr || pScreen == nullptr)
        return;

//    QRect deskRect = deskTopWidget->availableGeometry();
//    int count = deskTopWidget->screenCount();

    QRect screenRect = pScreen->geometry();
    int height = screenRect.height();
    int width = screenRect.width();
    qDebug() << __func__ << "------> primary screen width: " << width << " height: " << height;
    qDebug() << __func__ << " ratio: " << pScreen->devicePixelRatio();
    qDebug() << __func__ << " physicalSize: " << pScreen->physicalSize();
    qDebug() << __func__ << " availableSize: " << pScreen->availableSize();
    qDebug() << __func__ << " virtualSize: " << pScreen->virtualSize() << " virtualGeometry: " << pScreen->virtualGeometry();
    qDebug() << __func__ << " availableVirtualSize: " << pScreen->availableVirtualSize() << " availableVirtualGeometry: " << pScreen->availableVirtualGeometry();

    GpuInfo gpuInfo;
    gpuInfo.detect();
    qDebug() << __func__ << " gpuInfo: " << gpuInfo.toString();
}

void MainWindow::getJsonInfo(const char *msg)
{
    QJsonParseError jsonParseError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(msg, &jsonParseError);
    QJsonObject jsonObj = jsonDoc.object();

    auto getJsonValue = [=](const QJsonObject& jsonObj, const QString& key) {
        if (jsonObj.contains(key))
            return jsonObj[key];
        return QJsonValue();
    };

    int retType = getJsonValue(jsonObj, "type").toInt();
//    QVector<int> retVec = getJsonValue(jsonObj, "appIds").toArray();
    QJsonArray retArray = getJsonValue(jsonObj, "appIds").toArray();
//    QVector<double> retIntVec;
//    for (auto iArray : retArray) {
//        retIntVec.push_back(iArray.isDouble() ? iArray.toDouble() : 0);
//    }

    QStringList retStrList;
    for (auto iArray : retArray) {
        retStrList << (iArray.isDouble() ? QString::number(iArray.toDouble()) : "");
    }
    QVariantList retVarList = retArray.toVariantList();

    QStringList strAppIds;
//    std::for_each(retVarList.begin(), retVarList.end(), [&](double id){
//        strAppIds << QString::number(id);
//    });

//    std::for_each(retList.begin(), retList.end(), [&](int id) {
//        strAppIds << QString::number(id);
//    });

    qDebug() << __FUNCTION__ << "retType: " << retType << " strAppIds: " << strAppIds << " array: " << retArray << " retVarList: " << retVarList << " retStrList: " << retStrList;
}

void MainWindow::on_btn_test_clicked()
{
    qDebug() << __func__ << "----------> be called!";
    if (!m_uPtrTest) {
        m_uPtrTest = std::make_unique<FormTestDelete>();
        connect(this, &MainWindow::notifyTestSig, m_uPtrTest.get(), &FormTestDelete::onSlotBeCalled);
        connect(m_uPtrTest.get(), &FormTestDelete::notifyShadowSig, this, [](){
            qDebug() << __func__ << "-----------------> shadow sig be recv!!!!!!!!!!!!!!!!!!";
        });
    }

//    m_uPtrTest->changeText();
    emit notifyTestSig();
    hide();
    m_uPtrTest->show();
}

void MainWindow::on_btnTestHover_clicked()
{

}

void MainWindow::on_btnCreateReflectionObj_clicked()
{
    CReflection refObj;
    refObj.setName("");

    // normal call a func by string.
    QMetaObject::invokeMethod(&refObj, "func1");

    // output obj's name.
    qDebug() << __FUNCTION__ << "obj name: " << refObj.objectName();

    // set obj's property and output the obj's property.
    refObj.setProperty("refNameVal", "Hello Reflection!!");
    qDebug() << __FUNCTION__ << "::obj's property: " << refObj.property("refNameVal").toString();

    //
    QString nameStr = "Hello Qt!";
    QMetaObject::invokeMethod(&refObj, "setName", Qt::DirectConnection, Q_ARG(QString, nameStr));

    QMetaObject::invokeMethod(&refObj, "getName", Qt::DirectConnection, Q_RETURN_ARG(QString, nameStr));
    qDebug() << __FUNCTION__ << ":: 1, invoke [getName] result: " << nameStr;
}
